package com.itcast.spark.basePro

import org.apache.spark.ml.{Pipeline, PipelineModel}
import org.apache.spark.ml.classification.{DecisionTreeClassificationModel, DecisionTreeClassifier}
import org.apache.spark.ml.feature._
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.{SparkConf, SparkContext}

/**
 * DESC:
 */
object _08IrisFeaturesEngineerDescitionTree {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setAppName("_07IrisFeaturesEngineerDescitionTree").setMaster("local[*]")
    val spark: SparkSession = SparkSession.builder().config(conf).getOrCreate()
    val sc: SparkContext = spark.sparkContext
    sc.setLogLevel("WARN")
    //读取数据
    val dataDF: DataFrame = spark.read.format("csv").option("header", "true").option("inferschema", true).load("./datasets/mldata/iris.csv")
    dataDF.show()
    dataDF.printSchema()
    /* root
     |-- sepal_length: double (nullable = true)
     |-- sepal_width: double (nullable = true)
     |-- petal_length: double (nullable = true)
     |-- petal_width: double (nullable = true)
     |-- class: string (nullable = true)*/
    //1-将类别标签列转化为数值型--labelencoder
    val indexer: StringIndexer = new StringIndexer().setInputCol("class").setOutputCol("classlabel")
    val indexerModel: StringIndexerModel = indexer.fit(dataDF)
    //2-如何将dataDF变成向量
    val assembler: VectorAssembler = new VectorAssembler().setInputCols(Array("sepal_length", "sepal_width", "petal_length", "petal_width")).setOutputCol("features")
    //2-如何将selector特征选择
    val selector: ChiSqSelector = new ChiSqSelector().setLabelCol("classlabel").setFeaturesCol("features").setNumTopFeatures(2).setOutputCol("chiSqSelectorFea")
    //3-将数值列做归一化的操作--MinMaxScler
    val minMaxScaler: MinMaxScaler = new MinMaxScaler().setInputCol("chiSqSelectorFea").setOutputCol("minmaxfeatures")
    //4-准备一下决策树
    val classifier: DecisionTreeClassifier = new DecisionTreeClassifier()
      .setMaxDepth(5) //超参数
      .setFeaturesCol("minmaxfeatures")
      .setLabelCol("classlabel")
      .setPredictionCol("PredictLabel") //预测为那一列
      .setProbabilityCol("ProbabilityLabel") //以概率的方式输出当前的类别取值
    //5-将结果PredictLabel反转为业务中标签列的类型，到底属于那种花
    val indexToString: IndexToString = new IndexToString().setInputCol("PredictLabel").setOutputCol("beforeLabel").setLabels(indexerModel.labels)
    val pipeline: Pipeline = new Pipeline().setStages(Array(
      indexer,
      assembler,
      selector,
      minMaxScaler,
      classifier, //决策树 下标为4
      indexToString))
    val pipelineModel: PipelineModel = pipeline.fit(dataDF)
    pipelineModel.transform(dataDF).show()
    //打印树的结构----因为这里的决策树属于Pipeline的第5个阶段，使用asInstanceOf强制转化为DecisionTreeClassificationModel在进行打印
    println(pipelineModel.stages(4).asInstanceOf[DecisionTreeClassificationModel].toDebugString)
    //6-决策树模型需要评测？？？--AUC-Prescition

  }
}
